package com.hooper.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hooper.common.util.helper.HttpRequestHelper;
import com.hooper.hosp.client.HospClient;
import com.hooper.hosp.enums.PaymentStatusEnum;
import com.hooper.hosp.enums.PaymentTypeEnum;
import com.hooper.hosp.model.order.OrderInfo;
import com.hooper.hosp.model.order.PaymentInfo;
import com.hooper.hosp.vo.order.SignInfoVo;
import com.hooper.hospital.common.exception.HospitalException;
import com.hooper.hospital.common.result.ResultCodeEnum;
import com.hooper.hospital.common.utils.ObjectUtils;
import com.hooper.order.mapper.PaymentMapper;
import com.hooper.order.service.OrderService;
import com.hooper.order.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.hooper.hospital.common.result.ResultCodeEnum.*;

/**
 * @author Tim Hooper
 * @version 1.0
 * @time 2022/10/11/21:45
 */
@Service
@Slf4j
public class PaymentServiceImpl extends ServiceImpl<PaymentMapper, PaymentInfo> implements PaymentService {

    @Resource
    private HospClient hospClient;

    @Resource
    private OrderService orderService;

    @Override
    public void savePayInfo(OrderInfo order, Integer status) {
        if (ObjectUtils.isAnyNull(order, status)) {
            throw new HospitalException(ResultCodeEnum.PARAM_EMPTY);
        }

        if (!status.equals(PaymentTypeEnum.ALIPAY.getStatus()) && !status.equals(PaymentTypeEnum.WEIXIN.getStatus())) {
            throw new HospitalException(ResultCodeEnum.NO_SUCH_STATUES);
        }

        //查询该支付订单是否已创建
        LambdaQueryWrapper<PaymentInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentInfo::getOrderId, order.getId())
                .eq(PaymentInfo::getPaymentStatus, status).last("limit 1");
        Integer integer = baseMapper.selectCount(wrapper);
        if (integer == 1) {
            return;
        }

        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setCreateTime(new Date());
        paymentInfo.setOrderId(order.getId());
        paymentInfo.setPaymentType(status);
        paymentInfo.setOutTradeNo(order.getOutTradeNo());
        paymentInfo.setPaymentStatus(PaymentStatusEnum.UNPAID.getStatus());
        String subject = new DateTime(order.getReserveDate()).toString("yyyy-MM-dd") + "|" + order.getHosname() + "|" + order.getDepname() + "|" + order.getTitle();
        //支付的信息
        paymentInfo.setSubject(subject);
        paymentInfo.setTotalAmount(order.getAmount());
        baseMapper.insert(paymentInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccess(String outTradeNo, Integer payType, Map<String, String> result) {
        //判断是为微信支付
        if (payType != PaymentTypeEnum.WEIXIN.getStatus().intValue()) {
            return;
        }
        //通过订单号和支付状态获取支付信息
        PaymentInfo paymentInfo = this.getPaymentInfo(outTradeNo, payType);
        if (paymentInfo == null) {
            throw new HospitalException(NO_SUCH_DATA);
        }
        //更新支付状态
        PaymentInfo newPaymentInfo = new PaymentInfo();
        newPaymentInfo.setPaymentStatus(PaymentStatusEnum.PAID.getStatus());
        newPaymentInfo.setTradeNo(outTradeNo);
        newPaymentInfo.setCallbackTime(new Date());
        newPaymentInfo.setCallbackContent(result.toString());
        newPaymentInfo.setId(paymentInfo.getId());
        this.updateById(newPaymentInfo);
        //修改订单状态
        OrderInfo orderInfo = orderService.getById(paymentInfo.getOrderId());
        orderInfo.setOrderStatus(newPaymentInfo.getPaymentStatus());
        orderService.updateById(orderInfo);
        //调用医院接口，更新医院订单支付信息
        //获取医院签名
        SignInfoVo signInfoVo
                = hospClient.getSignInfoVo(orderInfo.getHoscode());
        log.info("获取到签名信息:{}",signInfoVo);
        if (null == signInfoVo) {
            throw new HospitalException(ResultCodeEnum.PARAM_ERROR);
        }
        //设置请求参数
        Map<String, Object> reqMap = new HashMap<>();
        reqMap.put("hoscode", orderInfo.getHoscode());
        reqMap.put("hosRecordId", orderInfo.getHosRecordId());
        reqMap.put("timestamp", HttpRequestHelper.getTimestamp());
        String sign = HttpRequestHelper.getSign(reqMap, signInfoVo.getSignKey());
        reqMap.put("sign", sign);
        //发送请求，获取请求参数
        JSONObject jsonResult = HttpRequestHelper.sendRequest(reqMap, signInfoVo.getApiUrl() + "/order/updatePayStatus");
        log.warn("接收到参数:{}",jsonResult);
        if (jsonResult.getInteger("code") != 200) {
            throw new HospitalException(jsonResult.getString("message"), ResultCodeEnum.FAIL.getCode());
        }
    }

    @Override
    public PaymentInfo getPaymentInfo(String outTradeNo, Integer payType) {
        if (StringUtils.isEmpty(outTradeNo)) {
            throw new HospitalException("订单号为空！", DATA_ERROR.getCode());
        }
        LambdaQueryWrapper<PaymentInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentInfo::getOutTradeNo, outTradeNo)
                .eq(PaymentInfo::getPaymentType, payType);
        return this.getOne(wrapper);
    }

    @Override
    public PaymentInfo getInfoByOrderId(String orderId, Integer payType) {
        if (StringUtils.isEmpty(orderId) || payType == null) {
            throw new HospitalException(PARAM_EMPTY);
        }
        LambdaQueryWrapper<PaymentInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentInfo::getOrderId, orderId)
                .eq(PaymentInfo::getPaymentType, payType);
        return baseMapper.selectOne(wrapper);
    }
}
